#include "HumanView.h"
GameAction* HumanView::cm_GameAction_NoAction = NULL;
HumanView::HumanView()
{
	//Init Human view members;
	m_ScreenElementList.push_back(ScreenElementPtr( RE_NEW Scene ) );
	if(cm_GameAction_NoAction == NULL)
		cm_GameAction_NoAction = RE_NEW GameAction("NoAction");
	//omfg almost forgot I haven't set the current scene
	m_pScene = dynamic_cast<Scene *>(m_ScreenElementList.back().get());
// add the listener also
	m_Listener = EventListenerPtr(RE_NEW HumanViewListener(this));
	REE()->VAddListener(m_Listener, EventData_NewActor::m_EventType); // global function to add a lsitener
	REE()->VAddListener(m_Listener, EventData_NewActorComponent::m_EventType);
	REE()->VAddListener(m_Listener, EventData_ActorComponentModified::m_EventType);
	REE()->VAddListener(m_Listener, EventData_Input_KeyUp::m_EventType);
	REE()->VAddListener(m_Listener, EventData_Input_KeyDown::m_EventType);
	REE()->VAddListener(m_Listener, EventData_Input_MouseMove::m_EventType);
}
HumanView::~HumanView()
{
	if(cm_GameAction_NoAction != NULL)
	{
		delete cm_GameAction_NoAction;
	}
	REE()->VRemoveListener(m_Listener, EventData_NewActor::m_EventType);
	REE()->VRemoveListener(m_Listener, EventData_NewActorComponent::m_EventType);
	REE()->VRemoveListener(m_Listener, EventData_ActorComponentModified::m_EventType);
	REE()->VRemoveListener(m_Listener, EventData_Input_KeyUp::m_EventType);
	REE()->VRemoveListener(m_Listener, EventData_Input_KeyDown::m_EventType);
	REE()->VRemoveListener(m_Listener, EventData_Input_MouseMove::m_EventType);
}
void HumanViewListener::HandleEvent(EventDataPtr EventData)
{
	const EventType evt(EventData->VGetEventType());
	if(evt == EventData_NewActorComponent::m_EventType)
	{
		//get the component
		EventData_NewActorComponent * evtdata = dynamic_cast<EventData_NewActorComponent*>(EventData.get());
		//check what type is it
		if(evtdata->m_Component->VGetBaseComponentType() == BaseRenderComponent::m_BaseComponentType)
		{
			BaseRenderComponent * cmp = dynamic_cast<BaseRenderComponent*>(evtdata->m_Component.get());

			m_View->m_pScene->VAddSceneNode(cmp->GetSceneNode());
		}
	}
	else if(evt == EventData_ActorComponentModified::m_EventType)
	{
		//get the component
		EventData_ActorComponentModified * evtdata = EventData->GetData<EventData_ActorComponentModified>();
		//first case. The component is transform
		if(evtdata->m_pcomponent->VGetBaseComponentType() == TransformComponent::m_BaseComponentType)
		{
			TransformComponent * cmp = dynamic_cast<TransformComponent*>(evtdata->m_pcomponent);
			dynamic_cast<SceneNode*>(m_View->m_pScene->VGetNodeById(cmp->m_pOwner->VGetId()))->m_Props.m_ToWorld = cmp->m_ToWorld;
		}
	}else if(evt == EventData_Input_KeyUp::m_EventType)
	{
		unsigned char ckey = dynamic_cast<EventData_Input_KeyUp*>(EventData.get())->m_ckey;
		m_View->ProcessKeyUp(ckey);
	}else if(evt == EventData_Input_KeyDown::m_EventType)
	{
		unsigned char ckey = dynamic_cast<EventData_Input_KeyDown*>(EventData.get())->m_ckey;
		m_View->ProcessKeyDown(ckey);
	}else if(evt == EventData_Input_MouseMove::m_EventType)
	{
		m_View->m_inputmap.m_mouse_x = dynamic_cast<EventData_Input_MouseMove*>(EventData.get())->m_mouse_x;
		m_View->m_inputmap.m_mouse_y = dynamic_cast<EventData_Input_MouseMove*>(EventData.get())->m_mouse_y;
	}

}

void HumanView::VOnRender()
{
	//Iterate trough all elements and call their render methods;
	if(m_ScreenElementList.size() > 0)
	{
		ScreenElementList::iterator begin = m_ScreenElementList.begin();
		while(begin != m_ScreenElementList.end())
		{
			(*begin)->VOnRender();
			begin++;
		}
	}
}
void HumanView::VOnUpdate(float fTime)
{
	//Iterate trough all elements and call their update methods;
	if(m_ScreenElementList.size() > 0)
	{
		ScreenElementList::iterator begin = m_ScreenElementList.begin();
		while(begin != m_ScreenElementList.end())
		{
			(*begin)->VOnUpdate(fTime);
			++begin;
		}
	}
	
}
void HumanView::ProcessKeyDown(const unsigned char key)
{
	m_inputmap.VKeyDown(key);
	//check if this key has an action
	GameAction action = m_inputmap.VIsActionMapped(key);
	if(action == *cm_GameAction_NoAction)
	{
		return;
	}
	ControllerList::iterator i = m_controllers.begin();
	while(i != m_controllers.end())
	{
		(*i)->VOnActionDown(action);
		++i;
	}
}
void HumanView::ProcessKeyUp(const unsigned char key)
{
	m_inputmap.VKeyUp(key);
	//check if this key has an action
	GameAction action = m_inputmap.VIsActionMapped(key);
	if(action == *cm_GameAction_NoAction)
	{
		return;
	}
	ControllerList::iterator i = m_controllers.begin();
	while(i != m_controllers.end())
	{
		(*i)->VOnActionUp(action);
		++i;
	}
}

bool InputMap::VIsTrue(const GameAction action)
{
	ActionMap::iterator actionmap_search = m_actionmap.find(action);
	if(actionmap_search == m_actionmap.end())
	{
		assert(0 && "Error. The requested action was not found.");
		return false;
	}
	KeyMap::iterator keymap_search = m_keymap.find(actionmap_search->second);
	if(keymap_search == m_keymap.end())
	{
		assert(0 && "Error. The requested key is not mapped.");
		return false;
	}
	return keymap_search->second;
}
void InputMap::VKeyDown(const unsigned char key)
{
	m_keymap[key] = true;
}
void InputMap::VKeyUp(const unsigned char key)
{
	m_keymap[key] = false;
}
void InputMap::VSetActionKey(const GameAction action, const unsigned char key)
{
	m_actionmap[action] = key;
}
void InputMap::VResetActionMap()
{
	m_actionmap.clear();
}
GameAction InputMap::VIsActionMapped(const unsigned char key)
{
	ActionMap::iterator i = m_actionmap.begin();
	while(i != m_actionmap.end())
	{
		if(i->second == key)
		{
			return i->first;
		}
		++i;
	}
	return *HumanView::cm_GameAction_NoAction;
}
